package ae.pcfc.cldos.online.common.manager.provider;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import ae.pcfc.cldos.online.common.clddb.domain.AppMetaData;
import ae.pcfc.cldos.online.common.clddb.domain.ApplicationStatus;
import ae.pcfc.cldos.online.common.clddb.domain.MessageInbox;
import ae.pcfc.cldos.online.common.clddb.domain.Process;
import ae.pcfc.cldos.online.common.clddb.domain.ServiceMaster;
import ae.pcfc.cldos.online.common.clddb.domain.manager.MessageInboxDOM;
import ae.pcfc.cldos.online.common.manager.BaseManager;
import ae.pcfc.cldos.online.common.manager.TaskAndNotificationsManager;
import ae.pcfc.cldos.online.common.strategy.mail.sender.IEmailSender;
import ae.pcfc.cldos.online.common.strategy.mail.sender.beans.StrategyMappingBean;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;

/**
 * 
 * @author arosa
 *
 */
public class TaskAndNotificationsManagerImpl extends BaseManager implements TaskAndNotificationsManager {

	private MessageInboxDOM messageInboxDOM;
	
	public void setMessageInboxDOM(MessageInboxDOM messageInboxDOM) {
		this.messageInboxDOM = messageInboxDOM;
	}
	
	private Map<String, IEmailSender> emails;
	
	public void setEmails(Map<String, IEmailSender> emails) {
		this.emails = emails;
	}
	
	private String[] ALL_PROCESSES = new String[]{
			Process.PROCESS_CANCEL_VISIT_VISA, Process.PROCESS_EMPLOYMENT_VISA,
			Process.PROCESS_EMPLOYMENT_VISA_CANCELATION, Process.PROCESS_EMPLOYMENT_VISA_RENEWAL,
			Process.PROCESS_NOC_LETTERS, Process.PROCESS_VISIT_VISA};
	
	private Long[] ALL_SERVICES = new Long[]{
			ServiceMaster.CANCEL_VV, ServiceMaster.EV_CANCELATION, ServiceMaster.EV_RENEVAL,
			ServiceMaster.NOC_LETTER, ServiceMaster.NV_ONE_MONTH, ServiceMaster.NV_THREE_MONTH,
			ServiceMaster.SERVICE_CODE_EMP_INSIDE, ServiceMaster.SERVICE_CODE_EMP_OUTSIDE,
			ServiceMaster.SERVICE_GTH, ServiceMaster.SERVICE_INTERNAL_TRANSFER};
	
	private List<StrategyMappingBean> emailsMappings = new ArrayList<StrategyMappingBean>();
	
	public TaskAndNotificationsManagerImpl(){
		addNewEmail(ALL_PROCESSES, 
					ALL_SERVICES, 
					new Long[]{ApplicationStatus.STATUS_APPROVED_BY_GENERAL_ADMIN}, "generalAdminApproveMail");
		
		addNewEmail(ALL_PROCESSES, 
				ALL_SERVICES, 
				new Long[]{ApplicationStatus.STATUS_REJECTED_BY_GENERAL_ADMIN}, "generalAdminRejectMail");
		
		addNewEmail(ALL_PROCESSES, 
				ALL_SERVICES, 
				new Long[]{ApplicationStatus.STATUS_CANCELED_BY_GENERAL_ADMIN}, "generalAdminCancelMail");
		
		addNewEmail(ALL_PROCESSES, 
				ALL_SERVICES, 
				new Long[]{ApplicationStatus.STATUS_INITIATED, ApplicationStatus.STATUS_RESUBMITED}, "subUserSubmitMail");
		
		addNewEmail(ALL_PROCESSES, 
				ALL_SERVICES, 
				new Long[]{ApplicationStatus.STATUS_REJECTED_BY_ONLINE_ADMIN}, "mainUserRejectMail");
		
		addNewEmail(ALL_PROCESSES, 
				ALL_SERVICES, 
				new Long[]{ApplicationStatus.STATUS_CANCELED_BY_ONLINE_ADMIN}, "mainUserCancelMail");
		
		addNewEmail(ALL_PROCESSES, 
				ALL_SERVICES, 
				new Long[]{ApplicationStatus.STATUS_APPROVED_BY_ONLINE_ADMIN}, "mainUserSubmitMail");
		
		
		addNewEmail(new String[]{Process.PROCESS_EMPLOYMENT_VISA}, 
				new Long[]{ServiceMaster.SERVICE_CODE_EMP_INSIDE, ServiceMaster.SERVICE_CODE_EMP_OUTSIDE, ServiceMaster.SERVICE_GTH, ServiceMaster.SERVICE_INTERNAL_TRANSFER}, 
				new Long[]{ApplicationStatus.PAYMENT_CANCELATION_COMPLETED}, "epCancelationPaymentMail");
		
		addNewEmail(new String[]{Process.PROCESS_EMPLOYMENT_VISA}, 
				new Long[]{ServiceMaster.SERVICE_CODE_EMP_INSIDE, ServiceMaster.SERVICE_CODE_EMP_OUTSIDE, ServiceMaster.SERVICE_GTH, ServiceMaster.SERVICE_INTERNAL_TRANSFER}, 
				new Long[]{ApplicationStatus.PAYMENT_RENEWAL_COMPLETED}, "epRenewalPaymentMail");
	}
	
	public void sendNotification(AppMetaData appMetaData, NotificationVO notificationVO) {
		IEmailSender iEmailSender = getEmailSender(appMetaData);
		if(iEmailSender!=null){
			iEmailSender.sendEmail(appMetaData, notificationVO);
		}
	}
	
	public void sendTask(AppMetaData appMetaData, Long taskCode) {
		MessageInbox messageInboxTask = new MessageInbox();
		messageInboxTask.setMiMsgType(MessageInbox.MESSAGE_TYPE_TASK);
		messageInboxTask.setMiSentOn(new Date());
		messageInboxTask.setMiActionFlag(MessageInbox.MESSAGE_ACTION_FLAG_NOT_DONE);
		messageInboxTask.setTackNameCode(taskCode);
		messageInboxTask.setAppId(appMetaData.getApplicationId());
		messageInboxDOM.add(messageInboxTask);
	}
	
	public void completeAllByAppId(Long appId){
		messageInboxDOM.completeAllApplicationTasks(appId);
	}
	
	private void addNewEmail(String[] processCodes, Long[] serviceCodes, Long[] statusCodes, String email){
		StrategyMappingBean strategyMappingBean = new StrategyMappingBean();
		strategyMappingBean.setProcessCodes(new HashSet<String>(Arrays.asList(processCodes)));
		strategyMappingBean.setServiceCodes(new HashSet<Long>(Arrays.asList(serviceCodes)));
		strategyMappingBean.setStatusCodes(new HashSet<Long>(Arrays.asList(statusCodes)));
		strategyMappingBean.setEmailName(email);
		emailsMappings.add(strategyMappingBean);
	}
	
	private String getEmailByAppMetaData(AppMetaData appMetaData){
		String result = null;
		String processCode = appMetaData.getProcessCode();
		Long serviceCode = appMetaData.getServiceCode();
		Long statusCode = appMetaData.getStatusCode();
		for(StrategyMappingBean strategyMappingBean : emailsMappings){
			Set<String> processCodes = strategyMappingBean.getProcessCodes();
			Set<Long> serviceCodes = strategyMappingBean.getServiceCodes();
			Set<Long> statusCodes = strategyMappingBean.getStatusCodes();
			if(processCodes.contains(processCode) &&
					serviceCodes.contains(serviceCode) &&
					statusCodes.contains(statusCode)){
				result = strategyMappingBean.getEmailName();
			}
		}
		return result;
	}
	
	private IEmailSender getEmailSender(AppMetaData appMetaData){
		String emailName = getEmailByAppMetaData(appMetaData);
		return emails.get(emailName);
	}
	
}
